gusucode.com > VC++ RingSDK界面库 > VC++ RingSDK界面库/code/libsrc/shell/browser.cpp

    /**********************************************************************
//
//
//        ##########                          ######  #########   # ######    #
//      #############                      ########### ######### #########  ###
//     ######## # ###  ##                 ############# ##    ## #####  # ####
//     ####  ##    ## ###                 ###     ### # #      #####   #####
//          #     ###  #            #     ##       ##  ##      ##     ###
//         ## ###### ##      ##  ####    ####          #       #     ##
//       #########  ###  ## ### #######   ######      ##      ##    ###
//      ######      ##  ######  ##  ##       ####     #      ##     ####
//     #######     ##   ###### ##  ###          ##   ##     ###    ######
//     #########   ##  ###### ## ######         ### ##    ###      #  #####
//    ##    ###### ####### ### #### ##  ## #######  ########      ##    ####
//    ##      #### ###  #  ### ### ##  ##########   ######       ##      ####
//   ##         ##                ##   #########    ####         #         ##
//               #              ###
//                              ##
//                             ###
//                             ##
//
//
//							Shell操作类库 ringShell.lib
//作者:临风
//
//版本:1.0
//
//声明:本类库可以自由使用而不须对作者作出任何回报,但作者希望能得到
//		  你的鼓励和支持。你可以对类库源码作出修改和改进,但希望你能在
//		  修改的同时给作者一份同样的副本。
//		  本类库不得用于任何商业用途,如确实需要,请与作者联系。
//
//e-mail:ringphone@sina.com
//
//原文件名:browser.cpp
//
//说明:浏览器控件操作实现
//
**********************************************************************/
#define MAKE_SELF_LIB
#include "ringshell.h"

typedef struct AAA
{
	LPITEMIDLIST	lpi;
	LPSHELLFOLDER	lpsfParent;
	LPITEMIDLIST	lpifq;
}TVITEMDATA,*LPTVITEMDATA;

typedef struct _STRRET1
{
    UINT uType; // One of the STRRET_* values
    union
    {
        LPWSTR          pOleStr;        // OLESTR that will be freed
        LPSTR           pStr;           // ANSI string that will be freed (needed?)
        UINT            uOffset;        // Offset into SHITEMID
        char            cStr[MAX_PATH]; // Buffer to fill in (ANSI)
    } ;//DUMMYUNIONNAME;
} STRRET1, *LPSTRRET1;

HWND hTreeWnd;

char szFoldername[MAX_PATH];
//NM_TREEVIEW *pNmTv=NULL;

void FillTreeView(HWND hwndTreeView,LPSHELLFOLDER lpsf,LPITEMIDLIST lpifq,	HTREEITEM hParent);
BOOL GetName( LPSHELLFOLDER lpsf, LPITEMIDLIST lpi, DWORD dwFlags, LPSTR lpFriendlyName) ;
LPITEMIDLIST CopyITEMID( LPMALLOC lpMalloc, LPITEMIDLIST lpi) ;
LPITEMIDLIST ConcatPidls( LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2) ;
LPITEMIDLIST GetFullyQualPidl( LPSHELLFOLDER lpsf, LPITEMIDLIST lpi) ;
void GetNormalAndSelectedIcons(LPITEMIDLIST lpifq,LPTV_ITEM lptvitem);
int GetIcon( LPITEMIDLIST lpi, UINT uFlags) ;
UINT GetSize(LPCITEMIDLIST pidl);
LPITEMIDLIST Create(UINT cbSize);
LPITEMIDLIST Next(LPCITEMIDLIST pidl);
void ExpandTree(void);

//初始化浏览器控件(nID为资源文件中树型控件的id)
BOOL Init_Browser(HWND hWnd,UINT nID)
{
	HIMAGELIST hImageList;
   LPSHELLFOLDER lpsf = 0 ;
   SHFILEINFO    sfi;
	HRESULT hr ;
	BOOL bOK;

	memset(szFoldername,0,MAX_PATH);
   hTreeWnd=GetDlgItem(hWnd,nID);

   hImageList = (HIMAGELIST)SHGetFileInfo((LPCSTR)"C:\\",
                                           0,
                                           &sfi,
                                           sizeof(SHFILEINFO),
                                           SHGFI_SYSICONINDEX | SHGFI_SMALLICON) ;

  	if(hImageList)
   	TreeView_SetImageList(hTreeWnd,hImageList,0);

	hr=SHGetDesktopFolder(&lpsf) ;

	if( SUCCEEDED(hr))
	{
	   TreeView_DeleteAllItems(hTreeWnd);
	   FillTreeView(hTreeWnd,lpsf,NULL,TVI_ROOT) ;
      ExpandTree();
      TreeView_SelectItem(hTreeWnd,TreeView_GetRoot(hTreeWnd));//,TVGN_FIRSTVISIBLE);
      bOK = TRUE;
	}
   else
   	bOK = FALSE;

	if(lpsf)
		lpsf->Release();
	return bOK;
}

//响应浏览器控件操作(在WM_NOTIFY消息中调用)
UINT Response_Browser(LONG lParam)
{
   NM_TREEVIEW *pnmtv = (NM_TREEVIEW *)lParam;
   LPTVITEMDATA lptvid ;
   HRESULT hr ;
   LPSHELLFOLDER lpsf2 = 0 ;

   switch( pnmtv -> hdr.code)
	{
		case TVN_SELCHANGED:
			lptvid = (LPTVITEMDATA)pnmtv -> itemNew.lParam;
         GetName(lptvid -> lpsfParent, lptvid->lpi, SHGDN_FORPARSING, szFoldername);

         if(szFoldername[1]!=':' || szFoldername[2]!='\\')
			{
		   	GetWindowsDirectory(szFoldername,MAX_PATH);
  				strcat(szFoldername,"\\desktop\0");
            TreeView_SelectItem(hTreeWnd,TreeView_GetRoot(hTreeWnd));
		   }
			return TVN_SELCHANGED;

		case TVN_ITEMEXPANDING:
		   if(( pnmtv -> itemNew.state & TVIS_EXPANDEDONCE))
				break ;

		   lptvid = (LPTVITEMDATA)pnmtv -> itemNew.lParam ;
		   hr=lptvid -> lpsfParent->BindToObject(lptvid -> lpi,
																   0,
																   IID_IShellFolder,
																   (LPVOID *)&lpsf2) ;

		   if( SUCCEEDED(hr))
		   {
			  FillTreeView(hTreeWnd,
								   lpsf2,
								   lptvid -> lpifq,
								   pnmtv -> itemNew.hItem) ;
		   }

		   TreeView_SortChildren(hTreeWnd, pnmtv -> itemNew.hItem, FALSE) ;
			return FALSE;//TVN_ITEMEXPANDING;

		default:
		   break;
   }
   return FALSE;
}

//得到在浏览器控件中用户选择的目录
LPSTR Get_Browser_selFoldername(void)
{
	return szFoldername;
}

LPITEMIDLIST Next(LPCITEMIDLIST pidl)
{
   LPSTR lpMem=(LPSTR)pidl;

   lpMem+=pidl -> mkid.cb;

   return (LPITEMIDLIST)lpMem;
}

UINT GetSize(LPCITEMIDLIST pidl)
{
    UINT cbTotal = 0;
    if( pidl)
    {
        cbTotal += sizeof(pidl -> mkid.cb) ;       // Null terminator
        while (pidl -> mkid.cb)
        {
            cbTotal += pidl -> mkid.cb;
            pidl = Next(pidl) ;
        }
    }

    return cbTotal;
}

LPITEMIDLIST Create(UINT cbSize)
{
    LPMALLOC lpMalloc;
    HRESULT  hr;
    LPITEMIDLIST pidl=NULL;

    hr=SHGetMalloc(&lpMalloc) ;

    if( FAILED(hr))
       return 0;

    pidl=(LPITEMIDLIST)lpMalloc->Alloc(cbSize) ;

    if(pidl)
        memset(pidl, 0, cbSize) ;      // zero-init for external task   alloc

    if(lpMalloc)
		 lpMalloc->Release() ;

    return pidl;
}

LPITEMIDLIST ConcatPidls(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
{
    LPITEMIDLIST pidlNew;
    UINT cb1;
    UINT cb2;

    if( pidl1)  //May be NULL
       cb1 = GetSize(pidl1) - sizeof(pidl1 -> mkid.cb) ;
    else
       cb1 = 0;

    cb2 = GetSize(pidl2) ;

    pidlNew = Create(cb1 + cb2) ;
    if( pidlNew)
    {
        if( pidl1)
           memcpy(pidlNew, pidl1, cb1) ;
        memcpy(((LPSTR)pidlNew) + cb1, pidl2, cb2) ;
    }
    return pidlNew;
}

LPITEMIDLIST CopyITEMID(LPMALLOC lpMalloc, LPITEMIDLIST lpi)
{
   LPITEMIDLIST lpiTemp;

   lpiTemp=(LPITEMIDLIST)lpMalloc->Alloc(lpi->mkid.cb+sizeof(lpi->mkid.cb));
   CopyMemory((PVOID)lpiTemp, (CONST VOID *)lpi, lpi -> mkid.cb+sizeof(lpi -> mkid.cb)) ;

   return lpiTemp;
}

BOOL GetName(LPSHELLFOLDER lpsf,LPITEMIDLIST  lpi,DWORD dwFlags,LPSTR lpFriendlyName)
{
   BOOL   bSuccess=TRUE;
   STRRET1 str;

   if(lpsf->GetDisplayNameOf(lpi,dwFlags,(LPSTRRET)&str)==NOERROR)
   {
      switch (str.uType)
      {
         case STRRET_WSTR:
            WideCharToMultiByte(CP_ACP,                 // CodePage
                                0,		               // dwFlags
                                str.pOleStr,            // lpWideCharStr
                                -1,                     // cchWideChar
                                lpFriendlyName,         // lpMultiByteStr
                                300,//sizeof(lpFriendlyName), // cchMultiByte,
                                NULL,                   // lpDefaultChar,
                                NULL) ;                  // lpUsedDefaultChar
             break;

         case STRRET_OFFSET:
             lstrcpy(lpFriendlyName, (LPSTR)lpi+str.uOffset) ;
             break;

         case STRRET_CSTR:
             lstrcpy(lpFriendlyName, (LPSTR)str.cStr) ;
             break;

         default:
             bSuccess = FALSE;
             break;
      }
   }
   else
      bSuccess = FALSE;

   return bSuccess;
}

LPITEMIDLIST GetFullyQualPidl(LPSHELLFOLDER lpsf, LPITEMIDLIST lpi)
{
   char szBuff[MAX_PATH];
   OLECHAR szOleChar[MAX_PATH];
   LPSHELLFOLDER lpsfDeskTop;
   LPITEMIDLIST  lpifq;
   ULONG ulEaten, ulAttribs;
   HRESULT hr;

   if( !GetName(lpsf, lpi, SHGDN_FORPARSING, szBuff))
      return NULL;

   hr=SHGetDesktopFolder(&lpsfDeskTop) ;

   if( FAILED(hr))
      return NULL;

   MultiByteToWideChar(CP_ACP,
					   MB_PRECOMPOSED,
					   szBuff,
					   -1,
					   szOleChar,
					   sizeof(szOleChar)) ;

   hr=lpsfDeskTop->ParseDisplayName(NULL,NULL,szOleChar,&ulEaten,&lpifq,&ulAttribs) ;

   lpsfDeskTop->Release() ;

   if( FAILED(hr))
      return NULL;

   return lpifq;
}

int GetIcon(LPITEMIDLIST lpi, UINT uFlags)
{
   SHFILEINFO    sfi;

   SHGetFileInfo((LPCSTR)lpi,
                 0,
                 &sfi,
                 sizeof(SHFILEINFO),
                 uFlags) ;

   return sfi.iIcon;
}

HICON GetFileIcon(LPSTR lpi)
{
   SHFILEINFO    sfi;

   SHGetFileInfo((LPCSTR)lpi,
                 0,
                 &sfi,
                 sizeof(SHFILEINFO),
                 SHGFI_ICON) ;

   return sfi.hIcon;
}

void GetNormalAndSelectedIcons(LPITEMIDLIST lpifq,
                               LPTV_ITEM lptvitem)
{
   lptvitem -> iImage = GetIcon(lpifq, SHGFI_PIDL |
                              SHGFI_SYSICONINDEX |
                              SHGFI_SMALLICON) ;

   lptvitem -> iSelectedImage = GetIcon(lpifq, SHGFI_PIDL |
                                      SHGFI_SYSICONINDEX |
                                      SHGFI_SMALLICON |
                                      SHGFI_OPENICON) ;
}


void FillTreeView(HWND hwndTreeView,LPSHELLFOLDER lpsf,LPITEMIDLIST lpifq,HTREEITEM hParent)
{
    TV_ITEM         tvi;                          // TreeView Item.
    TV_INSERTSTRUCT tvins;                        // TreeView Insert Struct.
    HTREEITEM       hPrev = NULL;                 // Previous Item Added.
    LPSHELLFOLDER   lpsf2=0;
    LPENUMIDLIST    lpe=0;
    LPITEMIDLIST    lpi=0,lpifqThisItem;// lpiTemp=0, lpifqThisItem;
    LPTVITEMDATA    lptvid=0;
    LPMALLOC        lpMalloc=0;
    ULONG           ulFetched;
    HRESULT         hr;
    char            szBuff[256];
    HWND            hwnd=GetParent(hwndTreeView);

    hr=SHGetMalloc(&lpMalloc);
    if(FAILED(hr))
       return;

    SetCapture(GetParent(hwndTreeView));
    SetCursor(LoadCursor(NULL,IDC_WAIT));

    hr=lpsf->EnumObjects(hwnd,
								SHCONTF_FOLDERS | SHCONTF_NONFOLDERS | SHCONTF_INCLUDEHIDDEN,
                        &lpe) ;

    if(SUCCEEDED(hr))
    {
	    while (S_OK==lpe->Next(1,&lpi,&ulFetched))
       {
          ULONG ulAttrs = SFGAO_HASSUBFOLDER | SFGAO_FOLDER;

          lpsf->GetAttributesOf(1,(LPCITEMIDLIST*)&lpi, &ulAttrs) ;

          if( ulAttrs & (SFGAO_HASSUBFOLDER | SFGAO_FOLDER))
          {
             if( ulAttrs & SFGAO_FOLDER)
             {
                tvi.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM;

                if( ulAttrs & SFGAO_HASSUBFOLDER)
                {
                   tvi.cChildren=1;
                   tvi.mask |= TVIF_CHILDREN;
                }

                lptvid = (LPTVITEMDATA)lpMalloc->Alloc(sizeof(TVITEMDATA));
                if( !lptvid)
                   goto Done;

                if(!GetName(lpsf, lpi, SHGDN_NORMAL, szBuff))
                   goto Done;
                tvi.pszText    = szBuff;
                tvi.cchTextMax = MAX_PATH;

                lpifqThisItem=ConcatPidls(lpifq, lpi) ;

                lptvid -> lpi=CopyITEMID(lpMalloc, lpi) ;

                GetNormalAndSelectedIcons(lpifqThisItem, &tvi) ;

                lptvid -> lpsfParent=lpsf;    //Store the parent folders SF
                lpsf->AddRef() ;

                if( hParent==TVI_ROOT)
                   lptvid -> lpifq=ConcatPidls(lpifq, lpi) ;
                else
                   lptvid -> lpifq=GetFullyQualPidl(lpsf, lpi) ;

                tvi.lParam = (LPARAM)lptvid;

                tvins./*DUMMYUNIONNAME.*/item = tvi;
                tvins.hInsertAfter = hPrev;
                tvins.hParent      = hParent;

                hPrev = TreeView_InsertItem(hwndTreeView, &tvins) ;

//////the next code expand all item but CD-ROM in Tree view/////////
//
//TreeView_Expand(hwndTreeView,hPrev,TVE_TOGGLE);
//
/////code end//////////////////////////////////////////////////////
				}

            lpMalloc->Free(lpifqThisItem) ;
            lpifqThisItem=0;
			}

         lpMalloc->Free(lpi) ;  //Finally, free the pidl that the shell gave us...
         lpi=0;
		}
	}

Done:

	ReleaseCapture() ;
   SetCursor( LoadCursor( NULL, IDC_ARROW)) ;

   if(lpe)
		lpe->Release() ;

   if(lpi && lpMalloc)
		lpMalloc->Free(lpi) ;
   if(lpifqThisItem && lpMalloc)
		lpMalloc->Free(lpifqThisItem) ;

   if(lpMalloc)
		lpMalloc->Release() ;
}

void ExpandTree(void)
{
   HTREEITEM hTree;

   hTree=TreeView_GetRoot(hTreeWnd);

   if(hTree)
   	TreeView_Expand(hTreeWnd,hTree,TVE_EXPAND);
}